home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_std / collection.e < prev    next >
Text File  |  2000-03-25  |  15KB  |  549 lines

  1. -- This file is  free  software, which  comes  along  with  SmallEiffel. This
  2. -- software  is  distributed  in the hope that it will be useful, but WITHOUT 
  3. -- ANY  WARRANTY;  without  even  the  implied warranty of MERCHANTABILITY or
  4. -- FITNESS  FOR A PARTICULAR PURPOSE. You can modify it as you want, provided
  5. -- this header is kept unaltered, and a notification of the changes is added.
  6. -- You  are  allowed  to  redistribute  it and sell it, alone or as a part of 
  7. -- another product.
  8. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  9. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  10. --                       http://SmallEiffel.loria.fr
  11. --
  12. deferred class COLLECTION[E]
  13. -- 
  14. -- Common abstract definition of a sequentiable collection of 
  15. -- objects. Such a collection is traversable using a simple 
  16. -- INTEGER index from `lower' to `upper'. Items can be added,
  17. -- changed or removed.
  18. -- 
  19. -- The SmallEiffel standard library (lib_std) provides four
  20. -- implementations : ARRAY[E], FIXED_ARRAY[E], LINK_LIST[E] 
  21. -- and LINK2_LIST[E]. All implementations have exactly the 
  22. -- same behavior. Switching from one implementation to another 
  23. -- only change the memory used and the execution time.
  24. --
  25.  
  26. inherit ANY redefine copy, is_equal, fill_tagged_out_memory end;
  27.  
  28. feature -- Indexing :
  29.  
  30.    lower: INTEGER is
  31.          -- Minimum index.
  32.       deferred
  33.       end;
  34.  
  35.    upper: INTEGER is
  36.          -- Maximum index.
  37.       deferred
  38.       end;
  39.  
  40.    frozen valid_index(index: INTEGER): BOOLEAN is
  41.          -- True when `index' is valid (ie. inside actual 
  42.          -- bounds of the collection).
  43.       do
  44.          Result := lower <= index and then index <= upper;
  45.       ensure      
  46.          Result = (lower <= index and then index <= upper);
  47.       end;
  48.  
  49. feature -- Counting :
  50.  
  51.    count: INTEGER is
  52.          -- Number of available indices.
  53.       deferred
  54.       ensure
  55.          Result = upper - lower + 1
  56.       end;
  57.  
  58.    is_empty: BOOLEAN is
  59.          -- Is collection empty ?
  60.       deferred
  61.       ensure
  62.      Result = (count = 0)
  63.       end;
  64.  
  65.    empty: BOOLEAN is
  66.       obsolete "The new name of this feature is `is_empty'."
  67.       do
  68.          Result := is_empty;
  69.       end;
  70.  
  71. feature -- Accessing :
  72.  
  73.    item, infix "@" (index: INTEGER): E is
  74.          -- Item at the corresponding `index'.
  75.       require
  76.          valid_index(index)
  77.       deferred
  78.       end;
  79.  
  80.    first: like item is
  81.          -- The very `first' item.
  82.       require
  83.          count >= 1
  84.       deferred
  85.       ensure
  86.          Result = item(lower)
  87.       end;
  88.    
  89.    last: like item is
  90.          -- The `last' item.
  91.       require
  92.          not is_empty
  93.       deferred
  94.       ensure
  95.          Result = item(upper)
  96.       end;
  97.  
  98. feature -- Writing :
  99.  
  100.    put(element: like item; index: INTEGER) is
  101.          -- Make `element' the item at `index'.
  102.       require
  103.          valid_index(index)
  104.       deferred
  105.       ensure
  106.          item(index) = element;
  107.          count = old count
  108.       end;
  109.  
  110.    swap(i1, i2: INTEGER) is
  111.          -- Swap item at index `i1' with item at index `i2'.
  112.       require
  113.          valid_index(i1);
  114.          valid_index(i2)
  115.       local
  116.          tmp: like item;
  117.       do
  118.          tmp := item(i1);
  119.          put(item(i2),i1);
  120.          put(tmp,i2);
  121.       ensure
  122.          item(i1) = old item(i2);
  123.          item(i2) = old item(i1);
  124.          count = old count
  125.       end;
  126.  
  127.    set_all_with(v: like item) is
  128.          -- Set all items with value `v'.
  129.       deferred
  130.       ensure
  131.          count = old count
  132.       end;
  133.    
  134.    set_slice_with(v: like item; lower_index, upper_index: INTEGER) is
  135.          -- Set all items in range [`lower_index' .. `upper_index'] with `v'.
  136.       require
  137.          lower_index <= upper_index;
  138.          valid_index(lower_index);
  139.          valid_index(upper_index)
  140.       local
  141.          i: INTEGER;
  142.       do
  143.          from  
  144.             i := lower_index;
  145.          until
  146.             i > upper_index
  147.          loop
  148.             put(v,i);
  149.             i := i + 1;
  150.          end;      
  151.       ensure
  152.          count = old count
  153.       end;
  154.    
  155.    clear_all is
  156.          -- Set every item to its default value.
  157.          -- The `count' is not affected (see also `clear').
  158.       local
  159.          value: like item;
  160.       do
  161.          set_all_with(value);
  162.       ensure
  163.      stable_upper: upper = old upper
  164.      stable_lower: lower = old lower
  165.          all_default
  166.       end;
  167.    
  168. feature -- Adding :
  169.  
  170.    add_first(element: like item) is
  171.          -- Add a new item in first position : `count' is increased by 
  172.          -- one and all other items are shifted right.
  173.       deferred
  174.       ensure
  175.          first = element;
  176.          count = 1 + old count;
  177.          lower = old lower;
  178.          upper = 1 + old upper
  179.       end;
  180.  
  181.    add_last(element: like item) is
  182.          -- Add a new item at the end : `count' is increased by one.
  183.       deferred
  184.       ensure
  185.          last = element;
  186.          count = 1 + old count;
  187.          lower = old lower;
  188.          upper = 1 + old upper
  189.       end;
  190.  
  191.    add(element: like item; index: INTEGER) is
  192.          -- Add a new `element' at rank `index' : `count' is increased 
  193.          -- by one and range [`index' .. `upper'] is shifted right
  194.          -- by one position.
  195.       require
  196.          lower <= index;
  197.          index <= upper + 1
  198.       deferred
  199.       ensure
  200.          item(index) = element;
  201.          count = 1 + old count;
  202.          upper = 1 + old upper
  203.       end;
  204.  
  205.    append_collection(other: COLLECTION[E]) is
  206.          -- Append `other' to Current.
  207.       require
  208.          other /= Void
  209.       local
  210.          i: INTEGER;
  211.       do
  212.          from
  213.             i := other.lower;
  214.          until
  215.             i > other.upper
  216.          loop
  217.             add_last(other.item(i));
  218.             i := i + 1;
  219.          end;
  220.       ensure
  221.          count = other.count + old count
  222.       end;
  223.  
  224. feature -- Modification :
  225.  
  226.    force(element: E; index: INTEGER) is
  227.          -- Make `element' the item at `index', enlarging the collection if 
  228.          -- necessary (new bounds except `index' are initialized with 
  229.          -- default values).
  230.       require
  231.          index >= lower
  232.       deferred
  233.       ensure
  234.          upper = index.max(old upper);
  235.          item(index) = element
  236.       end;
  237.  
  238.    copy(other: like Current) is
  239.      -- Reinitialize by copying all the items of `other'.
  240.       deferred
  241.       end;
  242.  
  243.    from_collection(model: COLLECTION[like item]) is
  244.      -- Initialize the current object with the contents of `model'.
  245.       require
  246.          model /= Void
  247.       deferred
  248.       ensure
  249.          count = model.count;
  250.       end;
  251.  
  252. feature -- Removing :
  253.  
  254.    remove_first is
  255.          -- Remove the `first' element of the collection.
  256.       require
  257.          not is_empty
  258.       deferred
  259.       ensure
  260.          count = (old count) - 1;
  261.          (lower = (old lower) + 1) xor (upper = (old upper) - 1) 
  262.       end;
  263.  
  264.    remove(index: INTEGER) is
  265.          -- Remove the item at position `index'. Followings items
  266.          -- are shifted left by one position.
  267.       require
  268.          valid_index(index)
  269.       deferred
  270.       ensure
  271.          count = (old count) - 1;
  272.          upper = (old upper) - 1;
  273.       end;
  274.  
  275.    remove_last is
  276.          -- Remove the `last' item.
  277.       require
  278.          not is_empty;
  279.       deferred
  280.       ensure
  281.          count = (old count) - 1;
  282.          upper = (old upper) - 1
  283.       end;
  284.  
  285.    clear is
  286.          -- Discard all items in order to make it `is_empty'.
  287.          -- See also `clear_all'.
  288.       deferred
  289.       ensure
  290.          is_empty;
  291.       end;
  292.  
  293. feature -- Looking and Searching :
  294.  
  295.    has(x: like item): BOOLEAN is
  296.          -- Look for `x' using `equal' for comparison.
  297.          -- Also consider `fast_has' to choose the most appropriate.
  298.       do
  299.          Result := valid_index(index_of(x));
  300.       end;
  301.    
  302.    fast_has(x: like item): BOOLEAN is
  303.          -- Look for `x' using basic `=' for comparison.
  304.          -- Also consider `has' to choose the most appropriate.
  305.       do
  306.          Result := valid_index(fast_index_of(x));
  307.       end;
  308.    
  309.    index_of(element: like item): INTEGER is
  310.          -- Give the index of the first occurrence of `element' using
  311.          -- `is_equal' for comparison.
  312.          -- Answer `upper + 1' when `element' is not inside.
  313.          -- Also consider `fast_index_of' to choose the most appropriate.
  314.       deferred
  315.       ensure
  316.          lower <= Result;
  317.          Result <= upper + 1;
  318.          Result <= upper implies equal(element,item(Result));
  319.       end;
  320.    
  321.    fast_index_of(element: like item): INTEGER is
  322.          -- Give the index of the first occurrence of `element' using
  323.          -- basic `=' for comparison.
  324.          -- Answer `upper + 1' when `element' is not inside.
  325.          -- Also consider `index_of' to choose the most appropriate.
  326.       deferred
  327.       ensure
  328.          lower <= Result;
  329.          Result <= upper + 1;
  330.          Result <= upper implies element = item(Result);
  331.       end;
  332.    
  333. feature -- Looking and comparison :
  334.  
  335.    is_equal(other: like Current): BOOLEAN is
  336.      -- Do both collections have the same `lower', `upper', and 
  337.      -- items?
  338.      -- The basic `=' is used for comparison of items.
  339.      -- See also `is_equal_map'.
  340.       deferred
  341.       ensure then
  342.      Result implies (lower = other.lower and upper = other.upper)
  343.       end;
  344.  
  345.    is_equal_map(other: like Current): BOOLEAN is
  346.      -- Do both collections have the same `lower', `upper', and 
  347.      -- items?
  348.      -- Feature `is_equal' is used for comparison of items.
  349.      -- See also `is_equal'.
  350.       deferred
  351.       ensure then
  352.      Result implies (lower = other.lower and upper = other.upper)
  353.       end;
  354.  
  355.    all_default: BOOLEAN is
  356.          -- Do all items have their type's default value?
  357.       deferred
  358.       end;
  359.  
  360.    frozen all_cleared: BOOLEAN is
  361.       obsolete "The new name of this feature is `all_default'."
  362.       do
  363.      Result := all_default;
  364.       end;
  365.  
  366.    same_items(other: COLLECTION[E]): BOOLEAN is
  367.      -- Do both collections have the same items? The basic `=' is used 
  368.      -- for comparison of items and indices are not considered (for 
  369.      -- example this routine may yeld true with `Current' indexed in 
  370.      -- range [1..2] and `other' indexed in range [2..3]).
  371.       require
  372.      other /= Void
  373.       local
  374.      i, j: INTEGER;
  375.       do
  376.      if count = other.count then
  377.         from
  378.            Result := true;
  379.            i := lower;
  380.            j := other.lower;
  381.         until
  382.            not Result or else i > upper
  383.         loop
  384.            Result := item(i) = other.item(i);
  385.            i := i + 1;
  386.            j := j + 1;
  387.         end;
  388.      end;
  389.       ensure
  390.      Result implies count = other.count
  391.       end;
  392.  
  393.    nb_occurrences(element: like item): INTEGER is
  394.          -- Number of occurrences of `element' using `equal' for comparison.
  395.          -- Also consider `fast_nb_occurrences' to choose the most appropriate.
  396.       deferred
  397.       ensure
  398.          Result >= 0
  399.       end;
  400.       
  401.    fast_nb_occurrences(element: like item): INTEGER is
  402.          -- Number of occurrences of `element' using basic `=' for comparison.
  403.          -- Also consider `nb_occurrences' to choose the most appropriate.
  404.       deferred
  405.       ensure
  406.          Result >= 0;
  407.       end;
  408.       
  409. feature -- Printing :
  410.  
  411.    frozen fill_tagged_out_memory is
  412.       local
  413.          i: INTEGER;
  414.          v: like item;
  415.       do
  416.          tagged_out_memory.append("lower: "); 
  417.          lower.append_in(tagged_out_memory);
  418.          tagged_out_memory.append(" upper: "); 
  419.          upper.append_in(tagged_out_memory);
  420.          tagged_out_memory.append(" [");
  421.          from  
  422.             i := lower;
  423.          until
  424.             i > upper or else tagged_out_memory.count > 2048
  425.          loop
  426.             v := item(i);
  427.             if v = Void then
  428.                tagged_out_memory.append("Void");
  429.             else
  430.                v.out_in_tagged_out_memory;
  431.             end;
  432.             if i < upper then
  433.                tagged_out_memory.extend(' ');
  434.             end;
  435.             i := i + 1;
  436.          end;
  437.          if i <= upper then
  438.             tagged_out_memory.append(" ..."); 
  439.          end;
  440.          tagged_out_memory.extend(']'); 
  441.       end;
  442.  
  443. feature -- Other Features :
  444.  
  445.    get_new_iterator: ITERATOR[E] is
  446.       deferred
  447.       end;
  448.  
  449.    replace_all(old_value, new_value: like item) is
  450.          -- Replace all occurrences of the element `old_value' by `new_value' 
  451.          -- using `equal' for comparison.
  452.          -- See also `fast_replace_all' to choose the apropriate one.
  453.       deferred
  454.       ensure
  455.          count = old count;
  456.          nb_occurrences(old_value) = 0
  457.       end;
  458.    
  459.    fast_replace_all(old_value, new_value: like item) is
  460.          -- Replace all occurrences of the element `old_value' by `new_value' 
  461.          -- using operator `=' for comparison.
  462.          -- See also `replace_all' to choose the apropriate one.
  463.       deferred
  464.       ensure
  465.          count = old count;
  466.          fast_nb_occurrences(old_value) = 0
  467.       end;
  468.  
  469.    move(lower_index, upper_index, distance: INTEGER) is
  470.          -- Move range `lower_index' .. `upper_index' by `distance' 
  471.          -- positions. Negative distance moves towards lower indices.
  472.          -- Free places get default values.
  473.       require
  474.          lower_index <= upper_index;
  475.          valid_index(lower_index);
  476.          valid_index(lower_index + distance);
  477.          valid_index(upper_index);
  478.          valid_index(upper_index + distance)
  479.       local
  480.          default_value: like item;
  481.          i: INTEGER;
  482.       do
  483.          if distance = 0 then
  484.          elseif distance < 0 then
  485.             from  
  486.                i := lower_index;
  487.             until
  488.                i > upper_index
  489.             loop
  490.                put(item(i),i + distance);
  491.                put(default_value,i);
  492.                i := i + 1;
  493.             end;
  494.          else
  495.             from  
  496.                i := upper_index;
  497.             until
  498.                i < lower_index
  499.             loop
  500.                put(item(i),i + distance);
  501.                put(default_value,i);
  502.                i := i - 1;
  503.             end;
  504.          end;
  505.       ensure
  506.          count = old count
  507.       end;
  508.  
  509.    slice(min, max: INTEGER): like Current is
  510.          -- New collection consisting of items at indexes in [`min'..`max']. 
  511.          -- Result has the same dynamic type as `Current'.
  512.      -- The `lower' index of the `Result' is the same as `lower'.
  513.       require
  514.          lower <= min;
  515.          max <= upper;
  516.          min <= max + 1
  517.       deferred
  518.       ensure
  519.          same_type(Result);
  520.          Result.count = max - min + 1;
  521.          Result.lower = lower
  522.       end;
  523.  
  524. feature {NONE}
  525.  
  526.    frozen equal_like(e1, e2: like item): BOOLEAN is
  527.          -- Note: this feature is called to avoid calling `equal'
  528.          -- on expanded types (no automatic conversion to 
  529.          -- corresponding reference type).
  530.       do
  531.          if e1.is_basic_expanded_type then
  532.             Result := e1 = e2;
  533.          elseif e1.is_expanded_type then
  534.             Result := e1.is_equal(e2);
  535.          elseif e1 = e2 then
  536.             Result := true;
  537.          elseif e1 = Void or else e2 = Void then
  538.          else
  539.             Result := e1.is_equal(e2);
  540.          end;
  541.       end;
  542.  
  543. invariant
  544.  
  545.    valid_bounds: lower <= upper + 1;
  546.  
  547. end -- COLLECTION[E]
  548.  
  549.